/**
 * @file Domain.h
 * @author Lishijie (lsj1018845759@outlook.com)
 * @brief 
 * @version 0.1
 * @date 2020-11-08
 * 
 * @copyright Copyright (c) 2020
 * 
 */
#ifndef _DOMAIN_H_
#define _DOMAIN_H_
#include "Point.h"

/**
 * @brief  计算区域类domain，所有计算区域类的基类。
 * 
 */
#define TEMPLATE template<Dimension DIM>

TEMPLATE
class Domain
{
typedef std::vector<Point<DIM> > PointList;
typedef int PointNum;
typedef int Rank;

public:

    /**
     * @brief Construct a new Domain object
     */
    Domain();

    /**
     * @brief Construct a new Domain object by vector<Point<DIM> > in std namespace;
     *        利用({{0,0},{1,0},{1,1},{0,1}})可以进行初始化；
     */
    Domain(const PointNum);

    /**
     * @brief Destroy the Domain object
     */
    ~Domain();

    /**
     * @brief 重载下标运算符operator[]
     * @param r 指定第几个几何点；
     * @return Point<DIM>& 几何点引用；
     */
    Point<DIM>& operator[](Rank r){return _Pointlist[r];};

protected:
    PointList _Pointlist;
};

TEMPLATE
Domain<DIM>::Domain()
{
    
}

TEMPLATE
Domain<DIM>::Domain(const PointNum num)
{
    _Pointlist.resize(num);
}

TEMPLATE
Domain<DIM>::~Domain()
{

}

struct IsRectangleException : public std::logic_error
{

    IsRectangleException(std::vector<Point<2U>> p):std::logic_error("Yours input doesn't make a reatangle in 2D!")
    {
        this -> p = p;
    }
    private:
    std::vector<Point<2U>> p;
};
/**
 * @brief 矩形计算区域类，继承Domain<2U>;
 * 
 */
class RectangleDomain:public Domain<2U>
{   
public:
    /**
    * @brief Construct a new Rectangle Domain object
    * 
    */
    RectangleDomain(){_Pointlist.resize(4);};
    /**
     * @brief Construct a new Rectangle Domain object
     * 
     */
    RectangleDomain(std::vector<Point<2>>);
    /**
     * @brief Destroy the Rectangle Domain object
     */
    ~RectangleDomain(){};
    /**
     * @brief 设置或返回矩形区域左下角
     * 
     * @return Point<2U>& 几何点引用
     */
    Point<2U>& LeftBottomPoint();
    /**
     * @brief 设置或返回矩形区域右下角
     * 
     * @return Point<2U>& 几何点引用
     */
    Point<2U>& RightBottomPoint();
    /**
     * @brief 设置或返回矩形区域右上角
     * 
     * @return Point<2U>& 几何点引用
     */
    Point<2U>& RightTopPoint();
    /**
     * @brief 设置或返回矩形区域左上角
     * 
     * @return Point<2U>& 几何点引用
     */
    Point<2U>& LeftTopPoint();
};

RectangleDomain::RectangleDomain(std::vector<Point<2>> p) 
{
     _Pointlist = p;
}
Point<2U>& RectangleDomain::LeftBottomPoint()
{
    return _Pointlist[0];
}

Point<2U>& RectangleDomain::RightBottomPoint()
{
    return _Pointlist[1];
}
Point<2U>& RectangleDomain::RightTopPoint()
{
    return _Pointlist[2];
}

Point<2U>& RectangleDomain::LeftTopPoint()
{

    return _Pointlist[3];
}
#undef TEMPLATE

#else
#endif
